/*
访问者模式（Visitor Pattern）是一种行为型设计模式，它允许你在不修改现有对象结构的情况下，定义对这些对象的新操作。
访问者模式将数据结构和对数据结构的操作分离开来，使得操作可以独立变化。

访问者模式的核心思想是，定义一个访问者（Visitor）类，该类中包含了对数据结构中每个元素的操作方法。
数据结构中的每个元素都要接受访问者的访问，并将自己作为参数传递给访问者的相应方法。
这样，访问者就可以通过访问元素的方法来操作元素。

使用访问者模式的优点包括：

1. 增加新的操作非常容易，只需要定义一个新的访问者类，并实现相应的操作方法即可，无需修改现有的元素类。
2. 将相关的操作集中在一个访问者类中，使得代码更加清晰和易于维护。
3. 可以对元素进行复杂的操作，而无需修改元素类的代码。

下面是一个使用访问者模式的C语言例程，该例程模拟了一个购物车结算的过程：
*/

#include <stdio.h>

// 具体元素1：苹果
typedef struct
{
    void (*accept)(struct ShoppingCartVisitor *visitor);
    double price;
    int quantity;
} Apple;

void acceptApple(struct ShoppingCartVisitor *visitor)
{
    visitor->visitApple(visitor, this);
}

// 具体元素2：书籍
typedef struct
{
    void (*accept)(struct ShoppingCartVisitor *visitor);
    double price;
    int quantity;
} Book;

void acceptBook(struct ShoppingCartVisitor *visitor)
{
    visitor->visitBook(visitor, this);
}

// 具体访问者：购物车访问者
typedef struct ShoppingCartVisitor
{
    void (*visitApple)(struct ShoppingCartVisitor *visitor, Apple *apple);
    void (*visitBook)(struct ShoppingCartVisitor *visitor, Book *book);
    double totalCost;
} ShoppingCartVisitor;

void visitApple(struct ShoppingCartVisitor *visitor, Apple *apple)
{
    double cost = apple->price * apple->quantity;
    visitor->totalCost += cost;
}

void visitBook(struct ShoppingCartVisitor *visitor, Book *book)
{
    double cost = book->price * book->quantity;
    visitor->totalCost += cost;
}

// 具体元素结构体
typedef struct
{
    Apple apple;
    Book book;
} ShoppingCart;

// 初始化购物车
void initShoppingCart(ShoppingCart *cart)
{
    cart->apple.price = 1.0;
    cart->apple.quantity = 2;
    cart->apple.accept = acceptApple;

    cart->book.price = 10.0;
    cart->book.quantity = 1;
    cart->book.accept = acceptBook;
}

int main()
{
    ShoppingCartVisitor visitor;
    visitor.totalCost = 0.0;
    visitor.visitApple = visitApple;
    visitor.visitBook = visitBook;

    ShoppingCart cart;
    initShoppingCart(&cart);

    cart.apple.accept(&visitor);
    cart.book.accept(&visitor);

    printf("Total cost: %.2f\n", visitor.totalCost);

    return 0;
}

/*
在上面的例程中，首先定义了两个具体元素类Apple和Book，它们分别表示购物车中的苹果和书籍。
每个具体元素类都实现了accept方法，用于接受访问者的访问。

然后，定义了一个具体访问者类ShoppingCartVisitor，它包含了对购物车中每个元素的操作方法。
在visitApple和visitBook方法中，根据元素的价格和数量计算出该元素的总价，并累加到访问者的totalCost属性中。

最后，在main函数中，初始化了一个购物车对象cart，并创建了一个访问者对象visitor。
通过调用具体元素的accept方法，将访问者传递给元素，并由元素调用访问者的相应方法。
这样，访问者就可以对购物车中的每个元素进行操作，并计算出购物车的总价。

通过访问者模式，我们可以将对数据结构的操作与数据结构本身分离开来，使得操作可以独立变化。
这样，当需要增加新的操作时，只需要定义一个新的访问者类，并实现相应的操作方法，无需修改现有的元素类。
*/